package keer.httpinterface.utils;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * IO工具类
 *
 * @author Keer
 * @since 1.0.0
 */
public final class IOUtils {
    private IOUtils() {

    }

    /**
     * 读取文本
     *
     * @param input 输入流
     * @return 文本
     * @throws IOException 读取异常
     */
    public static String readText(InputStream input) throws IOException {
        return readText(input, StandardCharsets.UTF_8.name());
    }

    /**
     * 读取文本
     *
     * @param input   输入流
     * @param charset 字符集
     * @return 文本
     * @throws IOException 读取异常
     */
    public static String readText(InputStream input, String charset) throws IOException {
        return readText(new InputStreamReader(input, charset));
    }

    /**
     * 从输入的Reader对象中读取文本内容
     * 此方法使用一个固定大小的字符数组作为缓冲区来读取数据，并将读取到的字符追加到StringBuilder中
     * 当没有更多字符可读取时，将读取到的字符转换为字符串并返回
     *
     * @param reader 输入的Reader对象，用于读取文本内容
     * @return 读取到的文本内容转换后的字符串
     * @throws IOException 如果在读取过程中发生I/O错误
     */
    public static String readText(Reader reader) throws IOException {
        // 创建一个8192字符的缓冲区，用于临时存储从reader读取的字符
        char[] buff = new char[8192];
        // 创建StringBuilder对象，用于累积读取到的字符
        StringBuilder sb = new StringBuilder();
        // 循环读取字符，直到reader中没有更多字符可读
        while (true) {
            // 从reader中读取字符到缓冲区，返回实际读取的字符数
            int c = reader.read(buff, 0, buff.length);
            // 如果没有字符读取到（返回值为-1），则结束循环
            if (c <= 0) {
                break;
            }
            // 将读取到的字符追加到StringBuilder中
            sb.append(buff, 0, c);
        }
        // 将累积的字符转换为字符串并返回
        return sb.toString();
    }

    /**
     * 将数据从一个输入流复制到一个输出流
     * 此方法主要用于在两个数据流之间高效传输数据，常用于文件复制或数据传输场景
     *
     * @param input  输入流，表示数据的来源
     * @param output 输出流，表示数据的目的地
     * @throws IOException 如果在读取输入流或写入输出流时发生错误，则抛出此异常
     */
    public static void copy(InputStream input, OutputStream output) throws IOException {
        // 创建一个缓冲区，用于临时存储从输入流读取的数据，以减少直接对输出流的操作次数
        byte[] buff = new byte[8192];
        // 无限循环读取输入流中的数据，直到输入流结束
        while (true) {
            // 从输入流中读取数据到缓冲区，返回值表示实际读取的字节数
            int c = input.read(buff);
            // 如果读取的字节数小于等于0，表示输入流已经结束，退出循环
            if (c <= 0) {
                break;
            }
            // 将缓冲区中的数据写入输出流，参数包括缓冲区、起始位置和写入长度
            output.write(buff, 0, c);
        }
    }

    /**
     * 静默关闭{@link Closeable}对象，忽略对象为空或者关闭时出现的异常
     *
     * @param o 可关闭对象
     */
    public static void closeQuietly(Closeable o) {
        if (o != null) {
            try {
                o.close();
            } catch (IOException ignored) {
            }
        }
    }

    /**
     * 将字符串转换为InputStream对象
     * 此方法使用默认字符集将字符串编码为字节数组，并创建一个ByteArrayInputStream对象
     * 如果需要指定字符集，请使用重载方法toStream(String str, String charset)
     *
     * @param str 要转换为InputStream的字符串
     * @return 包含编码后字符串的InputStream对象
     * @throws RuntimeException 如果默认字符集不受支持
     */
    public static InputStream toStream(String str) {
        try {
            // 调用重载方法，使用指定字符集转换字符串
            return toStream(str, ConstantUtils.DEFAULT_CHARSET);
        } catch (UnsupportedEncodingException e) {
            // 字符集不受支持时抛出运行时异常
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用指定字符集将字符串转换为InputStream对象
     *
     * @param str     要转换为InputStream的字符串
     * @param charset 字符集名称，用于编码字符串
     * @return 包含编码后字符串的InputStream对象
     * @throws UnsupportedEncodingException 如果指定的字符集不受支持
     */
    public static InputStream toStream(String str, String charset) throws UnsupportedEncodingException {
        // 创建并返回一个包含字符串编码后字节数组的ByteArrayInputStream对象
        return new ByteArrayInputStream(str.getBytes(charset));
    }
}

